package cn.wolfcode.ssm.util;

import cn.hutool.http.server.HttpServerRequest;
import cn.wolfcode.ssm.domain.OperationLog;
import cn.wolfcode.ssm.service.IOperationLogService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.sun.net.httpserver.HttpExchange;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component //把当前类注入到spring容器中
@Aspect    //把当前类标识为一个切面供容器读取
public class AopConfig {
    @Autowired
    private IOperationLogService operationLogService;
    @Autowired
    private HttpServletRequest httpServletRequest;


    //上下文Request容器
    /**
     * 指定切入点
     * 对贴有自定义注解@RequiredPermission的方法，进行切面
     */
    @Pointcut("@annotation(cn.wolfcode.ssm.util.RequireAnnotation)")
    private void useMethod() {
    }

    /**
     * 对切入点进行增强
     */
    @Around(value = "useMethod()")
    public Object recordLog(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        OperationLog operationLog = new OperationLog();//创建日志操作对象
        Date date = new Date();
        long startTime = date.getTime();//开始时间
        //执行处理方法（执行控制器中的方法）
        Object result = null;
        try {
            result = proceedingJoinPoint.proceed();//执行的方法
            operationLog.setResult(true);//没异常就设置成功

        } catch (Throwable throwable) {
            operationLog.setResult(false);//有异常设置失败
            throwable.printStackTrace();
            String message = throwable.getMessage();
            operationLog.setErrorMsg(message);//设置错误信息
        }
        //result是方法的返回值，直接return回去就会返回给springmvc处理
        long endTime = new Date().getTime();//结束时间
        long executeTime = endTime - startTime;//操作时间
        operationLog.setExecuteTime(executeTime);//设置操作时间

        operationLog.setOperationDate(date);


        //getSignature());是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
        Signature signature = proceedingJoinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            RequireAnnotation annotation = method.getAnnotation(RequireAnnotation.class);
            String name = annotation.name();//用户操作
            operationLog.setOperationName(name);//设置用户操作
            String expression = annotation.expression();//请求方法
            operationLog.setRequestMethod(expression);//设置请求方法
        }

        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = sra.getRequest();
        String ip = IPUtils.getIP(request);//获取当前操作用户的IP地址
        operationLog.setIpAddress(ip);//设置IP地址



        Map<String, String[]> parameterMap = request.getParameterMap();

        String string = JSON.toJSONString(parameterMap);
        operationLog.setRequestArgument(string);//设置参数


        String username = UserContext.getEmployee().getName();
        operationLog.setUsername(username);//设置用户名

        operationLogService.save(operationLog);

       /* requestURI.substring()
        request.getd*/
        return result;
    }


}